﻿//--------------------------------------------------------------------------
// <copyright file="ExceptionHandler.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// <summary>ExceptionHandler</summary>
//--------------------------------------------------------------------------
namespace MS.Msn.MediaSolutions.Common
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Diagnostics;
    using System.Reflection;
    using System.IO;

    /// <summary>
    /// ExceptionHandler
    /// </summary>
    public static class Exceptions
    {
        /// <summary>
        /// GetExString
        /// </summary>
        /// <param name="ex">exception instance</param>
        /// <param name="hasTime">has time tag</param>
        /// <returns>error string</returns>
        public static string GetExString(Exception ex, bool hasTime)
        {
            string itd = "    ";
            StringBuilder sb = new StringBuilder();

            if (ex != null)
            {
                string now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss,", Apps.DefaultCulture) + DateTime.Now.Millisecond;

                if (hasTime)
                {
                    sb.AppendLine(string.Format(Apps.DefaultCulture, "---- Err {0} ----", now));
                }

                sb.AppendLine(string.Format(Apps.DefaultCulture, "Message    :{0}{1}", itd, ex.Message));
                sb.AppendLine(string.Format(Apps.DefaultCulture, "Source     :{0}{1}", itd, ex.Source));

                sb.AppendLine("StackTrace :");
                sb.AppendLine(ex.StackTrace);

                if (!object.Equals(ex.Data, null) && (ex.Data.Count > 0))
                {
                    sb.AppendLine("Data       :");
                    foreach (object k in ex.Data.Keys)
                    {
                        sb.AppendLine(string.Format(Apps.DefaultCulture, "{0}{1}:{2}{3}", itd, k, itd, Xmls.EntityToXml(ex.Data[k])));
                    }
                }

                //sb.AppendLine(string.Format(AppDefiner.DefaultCulture, "StackTrace :{0}", GetStackTraceString(st)));

                if (!object.Equals(ex.InnerException, null))
                {
                    sb.AppendLine("---- Inner Exception ----");
                    sb.AppendLine(GetExString(ex.InnerException, false));
                }

                if (hasTime)
                {
                    sb.AppendLine(string.Format(Apps.DefaultCulture, "---- End {0} ----", now));
                }

                System.Diagnostics.Trace.Write(sb.ToString());
            }

            return sb.ToString();
        }

        /// <summary>
        /// GetExString
        /// </summary>
        /// <param name="ex">exception</param>
        /// <returns>error string</returns>
        public static string GetExString(Exception ex)
        {
            return GetExString(ex, true);
        }

        /// <summary>
        /// GetStackTraceString
        /// </summary>
        /// <param name="st"></param>
        /// <returns></returns>
        public static string GetStackTraceString(StackTrace st)
        {
            StringBuilder sb = new StringBuilder();

            if (st != null)
            {
                for (int i = 0, l = st.FrameCount; i < l; i++)
                {
                    StackFrame sf = st.GetFrame(i);
                    sb.Append(GetStackFrameString(sf));
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// GetStackFrameString
        /// </summary>
        /// <param name="sf">stack frame</param>
        /// <returns>stack frame infromation string</returns>
        public static string GetStackFrameString(StackFrame sf)
        {
            return GetStackFrameString(sf, false);
        }

        /// <summary>
        /// GetStackFrameString
        /// </summary>
        /// <param name="sf">stack frame</param>
        /// <param name="inpos">inclue line number or not</param>
        /// <returns>stack frame infromation string</returns>
        public static string GetStackFrameString(StackFrame sf, bool inpos)
        {
            StringBuilder sb = new StringBuilder();

            if (sf != null)
            {
                MemberInfo mi = sf.GetMethod();

                sb.AppendLine();
                sb.Append(string.Format(Apps.DefaultCulture, ">>>>{0}.{1}.{2}(", mi.DeclaringType.Namespace, mi.DeclaringType.Name, mi.Name));

                ParameterInfo[] prais = sf.GetMethod().GetParameters();
                for (int i = 0, l = prais.Length; i < l; i++)
                {
                    sb.Append(string.Format(Apps.DefaultCulture, "{0} {1}, ", prais[i].ParameterType.Name, prais[i].Name));
                }
                if (prais.Length > 0)
                {
                    sb.Remove(sb.Length - 2, 2);
                }
                sb.Append(")");
                sb.AppendLine();

                if (inpos)
                {
                    sb.Append("@@@@");
                    if (string.IsNullOrEmpty(sf.GetFileName()))
                    {
                        sb.Append(string.Format(Apps.DefaultCulture, "[Unknown file]: N {0:#00000}", sf.GetNativeOffset()));
                    }
                    else
                    {
                        sb.Append(string.Format(Apps.DefaultCulture, "{0}: Line {1:#0000}, Col {2:#0000}", Path.GetFileName(sf.GetFileName()), sf.GetFileLineNumber(), sf.GetFileColumnNumber()));

                        if (sf.GetILOffset() != StackFrame.OFFSET_UNKNOWN)
                        {
                            sb.Append(string.Format(Apps.DefaultCulture, ", IL {0:#0000}", sf.GetILOffset()));
                        }
                    }
                    sb.AppendLine();
                }
            }

            return sb.ToString();
        }
    }
}
